import axios, { AxiosResponse } from 'axios';
import { storage } from '../tools';
import { HOST, AUTH_TOKEN, OSS_UPLOAD_HOST, OSS_ACCESS_KEY_ID, UPLOAD_PERMISS_URL, UPLOAD_SIGN, UPLOAD_POLICY, UPLOAD_EXPIRE, TUploadCategory } from '../../constants';
import { setUploadData } from './ossUpload'

interface IAnyObject {
  [key: string]: any
}

interface IResponseData {
  code: number
  data: IAnyObject
  msg : string
}

const TIME_OUT = 60000

const axiosInstance = axios.create({
  baseURL: HOST,
  responseType: 'json',
  transformResponse: [
    function(data) {
      return data;
    }
  ],
  timeout: TIME_OUT
});

axiosInstance.interceptors.request.use(
  config => {
    config.headers.common['Authorization'] = storage.get(AUTH_TOKEN);
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);

axiosInstance.interceptors.response.use(
  (response: AxiosResponse<IResponseData>) => {
    return response
  },
  error => {
    const { response, message } = error
    // if (response.status === 401) {
		// 	storage.clear()
		// 	location.href = '/'
    // }
    if(message.indexOf(`timeout of ${TIME_OUT}ms`) >= 0) {
      // Vue.prototype.$message.error('网络超时')
    }
    const reason = response ? response.data : {}
    return Promise.reject(reason);
  }
);


// 验证授权是否过期
export function verifyUploadPermiss(): Promise<boolean> {
  return new Promise((resolve, reject) => {
    axiosInstance.get(UPLOAD_PERMISS_URL).then((res: AxiosResponse<IResponseData>) => {
      if(res.data.code === 200) {
        const { policy, signature, expireEndTime, host, accessKeyId } = res.data.data
        storage.set(UPLOAD_POLICY, policy);
        storage.set(UPLOAD_SIGN, signature);
        storage.set(UPLOAD_EXPIRE, expireEndTime);
        // oss host和accessKeyId由后端提供
        storage.set(OSS_UPLOAD_HOST, host);
        storage.set(OSS_ACCESS_KEY_ID, accessKeyId);
        resolve(true)
      } else {
        reject(false)
      }
    }, (err) => {
      reject(false)
    }).finally(() => {
      //
    })
  })
}

class Http {

  /**
   * get请求
   * @param url 请求链接
   * @param config 配置项
   */
  get(url: string, config?: any): Promise<any> {
    if(!(config && config.loading === false)) {
      // Vue.prototype.$loading.show()
    }
    return new Promise((resolve, reject) => {
      axiosInstance.get(url, config).then((res: AxiosResponse<IResponseData>) => {
        const { code, data, msg } = res.data
        if(code >= 200 && code < 300) {
          resolve(data)
        } else {
          if(!(config && config.error === false)){
            // Vue.prototype.$message.error(msg)
          }
          reject(msg)
        }
      }, (err) => {
        if(!(config && config.error === false)){
          // Vue.prototype.$message.error(err.msg)
        }
        reject(err.msg)
      }).finally(() => { })
    })
  }

  /**
   * post请求
   * @param url 请求链接
   * @param data 数据
   * @param config 配置项
   */
  post(url: string, data: IAnyObject, config?: any): Promise<any> {
    if(!(config && config.loading === false)) {
      // Vue.prototype.$loading.show()
    }
    return new Promise((resolve, reject) => {
      axiosInstance.post(url, data, config).then((res: AxiosResponse<IResponseData>) => {
        if(res.headers['content-type'].indexOf('application/json') >= 0) {
          const { code, data, msg } = res.data
          if(code >= 200 && code < 300) {
            resolve(data)
          } else {
            if(!(config && config.error === false)){
              // Vue.prototype.$message.error(msg)
            }
            reject(msg)
          }
        } else {
          resolve(res)
        }
      }, (err) => {
        if(!(config && config.error === false)){
          // Vue.prototype.$message.error(err.msg)
        }
        reject(err.msg)
      }).finally(() => { })
    })
  }

  /**
   * 上传文件
   * @param file 文件
   * @param category 文件种类(默认为身份证正面, category: id, isFront: true)
   */
  async upload(file: File | Blob, category: TUploadCategory, config?: any): Promise<string> {
    const [fd, key] = await setUploadData(file, category)
    const OssUploadHost = storage.get(OSS_UPLOAD_HOST) // 必须放在设置data后面(验证能获取host)
    return new Promise((resolve, reject) => {
      axiosInstance.post(OssUploadHost, fd, Object.assign(config || {}, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
      })).then((res: AxiosResponse<any>) => {
        if(res.status === 200){ // OSS上传成功会返回200
          resolve(key)
        } else {
          reject('Upload Failed!')
        }
      }, (err) => {
        // Vue.prototype.$notification.error({message: 'Upload Failed!', description: 'Please re-upload.'})
        reject('Upload Failed!')
      }).finally(() => { })
    })
  }
}

export default new Http();
